//
//  ViewController.m
//  UI25-GCD
//
//  Created by 韩旭 on 16/8/17.
//  Copyright © 2016年 lanou. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
  self.navigationItem.title = @"GCD";
    /* GCD 基于c语言，任何和对垒的概念程序员不需要管理线程的声明周期使用GCD 第一步：制定任务
     第二部：把任务添加到队列中队列分为：并行队列和串行队列
     */
  /*  容易混淆的概念!!
   并行和串行：决定了任务执行的方式 同步和异步：决定了是否具备开启新线程的能力
   使用提供好的全局队列（最后的DEFAULT代表队列的优先级）
  */
   
//    同步：在当前线程中执行（不具备创建新线程的能力）
//    dispatch_queue_t queue = DISPATCH_QUEUE_PRIORITY_DEFAULT;
//    dispatch_sync(queue, ^{
//       定制的任务（耗时操作）
//    });
//    异步：在新线程中执行
//    dispatch_async(queue, ^{
//       制定的任务（耗时操作）
//    });
    [self GCD的apply];
//    总结;GCD 里，非主队列情况下只有异步函数才会开启新鲜曾
//    ，此时如果是并发队列，会开启多条线程，如果是串行队列，只会开启一条线程，其他情况下（包括主队列）都不会开启新的线程，并且是串行执行任务
    
//     [self 创建并发队列];
}
//1.串行队列+同步
- (void)test2 {
//    创建方法
    dispatch_queue_t queue = dispatch_queue_create("queue.one", 0);
    dispatch_sync(queue, ^{
        
        NSLog(@"download1 - %@", [NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        
        NSLog(@"download2 - %@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        
        NSLog(@"download3 - %@", [NSThread currentThread]);
    });
//    同样，此时也是不会创建子线程的，所有任务是在主线程中也是串行执行, 和同步并行队列是一样的效果
    
}
//2 串行队列+异步
- (void)test3 {
    dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        
        NSLog(@"download1- %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        
        NSLog(@"download2- %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        
        NSLog(@"download3- %@", [NSThread currentThread]);
    });
//    队列只开启了一条子线程，去一个接着一个任务去执行,这种方式对任务执行的效率没有任何提高
}
//3 并行对列+同步
- (void)test4 {
//    创建队列
    /*第一个参数：c语言的字符串，标签
     第二个参数：队列的类型
     */
    dispatch_queue_t queue = dispatch_queue_create("downLoad", DISPATCH_QUEUE_CONCURRENT);
//    制定任务（多任务）
    dispatch_sync(queue, ^{
        
        NSLog(@"downLoad1 - %@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"download3- %@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"download4-%@", [NSThread currentThread]);
    });
//    同步函数是不会开启子线程的， 所有任务都是在主线程中串行进行
    
}
//4 并行队列+异步 这种组合需要掌握
- (void)test5 {
    dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"download1 - %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"download2 - %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"download3 - %@", [NSThread currentThread]);
    });
//    可以看出队列开启了三条子线程区分别执行三个任务，队列中的任务是并发执行的。在这里有个注意点：
//    并不是说有多少任务GCD 就会执行多少条线程具体开启几条线是由系统决定的
}

- (void)异步函数和主队列 {
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"download1 - %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"download2 - %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"download3 - %@", [NSThread currentThread]);
    });
//    主队列所有的任务确实是在主线程执行的，虽然是异步函数， 但也不会开启子线程
}
// GCD代码延迟
- (void)用GCD代码延迟 {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"GCD在主线程-%@", [NSThread currentThread]);
    });
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"在子线程中：%@" , [NSThread currentThread]);
    });
}

- (void)创建并发队列 {
    
//    创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("group", DISPATCH_QUEUE_CONCURRENT);
//    异步函数
    dispatch_async(queue, ^{
        for (int i = 0 ; i < 10; i++) {
            NSLog(@"download1 _ %@", [NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0 ; i < 10; i++) {
            NSLog(@"download2 _ %@", [NSThread currentThread]);
        }
        
//    GCD的栏删函数
//        注意：栏删函数不能是用全局并发队列
//        在异步函数中控制任务执行的顺序，只有当栏删函数执行完毕后才会执行后面的任务
    dispatch_barrier_async(queue, ^{
            
            NSLog(@"+++++++++");
        });
        
    });
    dispatch_async(queue, ^{
        for (int i = 0 ; i < 10; i++) {
            NSLog(@"download3 _ %@", [NSThread currentThread]);
        }
        
    });
    
}
- (void)GCD的apply {
//    NSDate* tmpStartData = [NSDate date];
//    
//    for (int i = 0; i < 10000; ++i) {
//        NSLog(@"for- %d -- %@", i, [NSThread currentThread]);
//    }
//    
//    double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
//    NSLog(@"for 耗时 = %f", deltaTime);
    
    NSDate* tmpStartData = [NSDate date];
    
    /*
     第一个参数: 迭代次数
     第二个参数: 线程队列(并发队列)
     第三个参数: index 索引
     */
    dispatch_apply(10000, dispatch_get_global_queue(0, 0), ^(size_t index) {
        NSLog(@"GCD- %zd -- %@", index, [NSThread currentThread]);
    });
    
    double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
    NSLog(@"GCD 耗时 = %f", deltaTime);
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end